import * as step from '@ali/flow-step-toolkit'
import * as sinon from 'sinon';
import * as fs from 'fs';
// @ts-ignore
import {RemoteStorage} from '../src/storage';
// @ts-ignore
import {mockIParams} from './cache.spec';

const proxyquire = require('proxyquire');

let remoteStorage: RemoteStorage;
let statStub: sinon.SinonStub;
let putStub: sinon.SinonStub;
let getStub: sinon.SinonStub;
let sandbox = sinon.createSandbox();
let stepExecStub: sinon.SinonStub;


describe('download', () => {
    beforeEach(() => {
        stepExecStub = sandbox.stub(step.exec, 'call').returns(Promise.resolve(0));

        statStub = sandbox.stub();
        putStub = sandbox.stub();
        getStub = sandbox.stub();
        remoteStorage = {
            stat: statStub,
            put: putStub,
            get: getStub
        }
    });

    afterEach(() => {
        sandbox.restore();
    });

    const fsStub = {
        statSync: sinon.stub()
    };
    const {download} = proxyquire('../src/download', {
        fs: fsStub
    })

    it('should skip if cache does not exist', async () => {
        const params = mockIParams()
        params.fileID = 'test-file-id';
        const artifactFullName = 'test-artifact-full-name';

        statStub.resolves(false);

        await download(remoteStorage, params, artifactFullName);

        sinon.assert.calledWith(statStub, params.fileID);
        sinon.assert.notCalled(getStub);
    });

    it('should fetch cache successfully and log size', async () => {
        const params = mockIParams()
        params.fileID = 'test-file-id';
        const artifactFullName = 'test-artifact-full-name';
        const mockResult = {
            res: {
                status: 200,
            }
        };

        statStub.resolves(true);
        getStub.resolves(mockResult);
        fsStub.statSync.returns({size: 100});

        await download(remoteStorage, params, artifactFullName);

        sinon.assert.calledWith(statStub, params.fileID);
        sinon.assert.calledWith(getStub, params.fileID, artifactFullName);
        sinon.assert.calledWith(fsStub.statSync, artifactFullName);
    });

    it('should abort upload if cache size exceeds limit', async () => {
        const params = mockIParams()
        params.fileID = 'test-file-id';
        const artifactFullName = 'test-artifact-full-name';
        const mockResult = {
            res: {
                status: 200,
            }
        };

        statStub.resolves(true);
        getStub.resolves(mockResult);
        fsStub.statSync.returns({size: 2 * 1000 * 1000 * 1000 + 100});

        await download(remoteStorage, params, artifactFullName);
        sinon.assert.calledWith(statStub, params.fileID);
        sinon.assert.calledWith(getStub, params.fileID, artifactFullName);
        sinon.assert.calledWith(fsStub.statSync, artifactFullName);
    });

});